package pwd.allen.writeHandler;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.AbstractCellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import pwd.allen.DicItem;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据字典映射
 *
 * 相比于Converter，这种支持默认值的处理
 * 如果属性值为null，不会走afterCellDataConverted，但是会走afterCellDispose
 *
 * @author pwdan
 * @create 2021-10-19 17:31
 **/
public class DicItemWriteHandler extends AbstractCellWriteHandler {

    private Map<String, DicItem> mapField = new HashMap<>();

    /**
     * 初始化Map映射关系的行
     */
    private Integer intRow2InitMap = null;

    private Map<String, Map<String, String>> map_dic = new HashMap<>();

    {
        // 这里实际项目中可以改成从数据库中读取，这里先写死
        map_dic.put("str数据字典", MapUtil.<String, String>builder().put("str1", "字符串1").put("str2", "字符串2").build());
        map_dic.put("int数据字典", MapUtil.<String, String>builder().put("1", "数字1").put("2", "数字2").build());
    }

    /**
     * 这里我用来做映射处理
     */
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        if (isHead || StrUtil.isEmpty(head.getFieldName()) || cellDataList.size() == 0) {
            return;
        }
        if (intRow2InitMap == null) {
            intRow2InitMap = relativeRowIndex;
        }
        if (relativeRowIndex.equals(intRow2InitMap)) {
            // 初始化字段的数据字典映射配置
            Field field = ReflectUtil.getField(writeSheetHolder.getClazz(), head.getFieldName());
            DicItem annotation = field.getAnnotation(DicItem.class);
            if (annotation != null) {
                mapField.put(head.getFieldName(), annotation);
            }
        }
        CellData cellData = cellDataList.get(0);
        DicItem dicItem = mapField.get(head.getFieldName());
        if (dicItem != null) {
            // 如果有配置数据字典映射，则操作之
            if (cellData.getType() == CellDataTypeEnum.EMPTY) {
                if (StrUtil.isNotEmpty(dicItem.def())) {
                    cell.setCellValue(dicItem.def());
                }
            } else if (cellData.getType() == CellDataTypeEnum.STRING) {
                String value = cellData.getStringValue();
                if (StrUtil.isEmpty(value) && StrUtil.isNotEmpty(dicItem.def())) {
                    cell.setCellValue(dicItem.def());
                    return;
                }
                if (StrUtil.isNotEmpty(dicItem.json())) {
                    JSONObject jsonObject = JSONUtil.parseObj(dicItem.json());
                    cell.setCellValue(jsonObject.getStr(value, value));
                } else if (dicItem != null && map_dic != null) {
                    Map<String, String> dic = map_dic.get(dicItem.value());
                    if (dic != null && dic.containsKey(value)) {
                        cell.setCellValue(dic.get(value));
                    }
                }
            } else if (cellData.getType() == CellDataTypeEnum.NUMBER) {
                BigDecimal value = cellData.getNumberValue();
                if (StrUtil.isNotEmpty(dicItem.json())) {
                    JSONObject jsonObject = JSONUtil.parseObj(dicItem.json());
                    cell.setCellValue(jsonObject.getStr(value.toString(), value.toString()));
                } else if (dicItem != null && map_dic != null) {
                    Map<String, String> dic = map_dic.get(dicItem.value());
                    if (dic != null && dic.containsKey(value.toString())) {
                        cell.setCellValue(dic.get(value.toString()));
                    }
                }
            } else if (cellData.getType() == CellDataTypeEnum.BOOLEAN) {
                // TODO
            }
        }
    }
}
